home *** CD-ROM | disk | FTP | other *** search
- /*
- EGSFlick - Frank Neumann, November 1993
-
- This file, read.c, was taken over from the original xflick
- source almost without any modifications - except for these
- comments, the include file change below, and a call to the
- new error/exit routine 'Crash' instead of 'xferror'.
- Here is the original comment:
-
- xflick - Ron Schnell, March, 1991
-
- This code is provided as is, with no warrantees, expressed
- or implied. I believe this code to be free of encumbrance,
- and offer it to the public domain. I ask, however, that
- this paragraph and my name be retained in any modified
- versions of the file you may make, and that you notify me
- of any improvements you make to the code.
-
- Ron Schnell (ronnie@sos.com)
-
-
- The following changes are from Michael Pall
- (pall@rz.uni-karlsruhe.de) Mar 25-28 1991:
-
- Lots of bugfixes and changes to the structure of the files.
- The interpretation part is now in this file.
- */
-
- /* This is read.c, the functions which read in FLI structures in
- a machine independent format. */
-
-
- #include <stdio.h>
- #include <sys/types.h>
- #include "eflick.h"
-
- #define TRUE 1
- #define FALSE 0
-
- #define DEBUGGING 0
-
- extern int verbose;
- extern void Crash( char *);
-
- void
- read_flihead(fd, header)
- int fd;
- struct fli_header *header;
- {
- unsigned char *buf = (unsigned char *)malloc(SIZE_HEADER);
- unsigned char *sbf;
- int i;
-
- sbf = buf;
- (void) read(fd, buf, SIZE_HEADER);
- header->fhd_size = get_long(buf);
- buf += LONGSIZE;
-
- header->fhd_magic = get_short(buf);
- buf += SHORTSIZE;
-
- header->fhd_frames = get_short(buf);
- buf += SHORTSIZE;
-
- header->fhd_width = get_short(buf);
- buf += SHORTSIZE;
-
- header->fhd_height = get_short(buf);
- buf += SHORTSIZE;
-
- header->fhd_gap = get_short(buf);
- buf += SHORTSIZE; /* nothing */
-
- header->fhd_flags = get_short(buf);
- buf += SHORTSIZE; /* flags */
-
- header->fhd_speed = get_short(buf);
- buf += SHORTSIZE;
-
- header->fhd_next = get_long(buf);
- buf += LONGSIZE;
-
- header->fhd_frit = get_long(buf);
- buf += LONGSIZE;
-
- bcopy(buf, header->fhd_expand, FHD_EXPAND_SIZE);
-
- free(sbf);
-
- if (verbose) {
- fprintf(stderr, "header->fhd_size: %d\n", header->fhd_size);
- fprintf(stderr, "header->fhd_magic: 0x%x\n", header->fhd_magic);
- fprintf(stderr, "header->fhd_frames: %d\n", header->fhd_frames);
- fprintf(stderr, "header->fhd_width: %d\n", header->fhd_width);
- fprintf(stderr, "header->fhd_height: %d\n", header->fhd_height);
- fprintf(stderr, "header->fhd_gap: 0x%x\n", header->fhd_gap);
- fprintf(stderr, "header->fhd_flags: 0x%x\n", header->fhd_flags);
- fprintf(stderr, "header->fhd_speed: %d\n", header->fhd_speed);
- fprintf(stderr, "header->fhd_next: %d\n", header->fhd_next);
- fprintf(stderr, "header->fhd_frit: 0x%x\n", header->fhd_frit);
- fprintf(stderr, "header->fhd_expand: ");
- for (i = 0; i < FHD_EXPAND_SIZE; i++)
- fprintf(stderr, "%x ", 0xff & (unsigned int)header->fhd_expand[i]);
- fprintf(stderr, "\n");
- }
- }
-
- void
- read_fheader(fd, fheader)
- int fd;
- struct frame_header *fheader;
- {
- unsigned char data[SIZE_FHEADER];
- unsigned char *buf = data;
- int ret;
- unsigned char tmp;
- int syncNotFound = TRUE;
- int i;
-
- /* Syncronize to the magic word */
- i = 0;
- do {
- ret = read(fd, &tmp, 1);
- ++i;
- if (verbose)
- fprintf(stderr, "read1 i: %d tmp: 0x%x sync: %d\n",
- i, 0xff & (unsigned int)tmp, syncNotFound);
- if (tmp == (unsigned char)0xfa) {
- ret = read(fd, &tmp, 1);
- ++i;
- if (tmp == (unsigned char)0xf1)
- syncNotFound = FALSE;
- else
- syncNotFound = TRUE;
- if (verbose)
- fprintf(stderr, "read2 i: %d tmp: 0x%x sync: %d\n",
- i, 0xff & (unsigned int)tmp, syncNotFound);
- }
- } while((syncNotFound == TRUE) && (ret > 0));
-
- if (ret < 0) {
- fprintf(stderr,
- "Error reading input file looking for frame header magic number. i: %d\n", i);
- exit(-1);
- }
-
- if (verbose)
- fprintf(stderr, "After Sync i: %d sync: %d ret: %d\n",
- i, syncNotFound, ret);
-
- if ((ret = lseek(fd, -6, SEEK_CUR)) < 0) {
- perror("Seeking to begining of frame");
- exit(-1);
- }
-
- (void) read(fd, buf, SIZE_FHEADER);
-
- fheader->fr_size = get_long(buf);
- buf += LONGSIZE;
- fheader->fr_magic = get_short(buf);
- buf += SHORTSIZE;
- fheader->fr_chunks = get_short(buf);
- bcopy(buf, fheader->fr_expand, FR_EXPAND_SIZE);
-
-
- if (verbose) {
- fprintf(stderr, "fheader->fr_size: %d\n", fheader->fr_size);
- fprintf(stderr, "fheader->fr_magic: 0x%x\n", fheader->fr_magic);
- fprintf(stderr, "fheader->fr_chunks: %d\n", fheader->fr_chunks);
- fprintf(stderr, "fheader->fr_expand: ");
- for (i = 0; i < FR_EXPAND_SIZE; i++)
- fprintf(stderr, "%d ", 0xff & (unsigned int)fheader->fr_expand[i]);
- fprintf(stderr, "\n");
- }
-
- }
-
- void
- read_chunk(fd, chunk)
- int fd;
- struct chunk_header *chunk;
- {
- unsigned char data[SIZE_CHEADER];
- unsigned char *buf = data;
-
- (void) read(fd, buf, SIZE_CHEADER);
- chunk->ch_bytes = get_long(buf);
- buf += LONGSIZE;
- chunk->ch_type = get_short(buf);
-
- if (verbose) {
- fprintf(stderr, "chunk->ch_bytes: %d\n", chunk->ch_bytes);
- fprintf(stderr, "chunk->ch_type: %d\n", chunk->ch_type);
- }
- }
-
- void
- interpret_fli(fd,header,data,notfirst,func)
- int fd; /* The file descriptor */
- struct fli_header *header; /* The header of the file */
- unsigned char *data; /* A pointer to the pixel data */
- int notfirst; /* Is this not the first time through? */
- void (*func)(); /* The function that stores or displays the chunks */
- {
- int i, j, s, l, k; /* Random look/status ints */
- short ndiff; /* To hold the # lines changed from last frame */
- struct frame_header fheader; /* To hold each frame header */
- struct chunk_header chunk; /* To hold each chunk header */
- unsigned char *buf=(unsigned char *)0;
- /* malloc'd space to hold each chunk */
- int bufalloc; /* Space already allocated for buf */
- int skchange, skcount, sicount; /* Various pixel/data index's */
- unsigned char *cptr,*dptr,*eptr; /* data pointers into *buf */
- int npack; /* Number of packets in this chunk */
- unsigned char by, by0, by1; /* To hold a byte */
- int curx, cury; /* The current x & y coords */
- short wwidth, wheight; /* Width and height of the window */
- int topy,bottomy,leftx,rightx; /* For optimizing FLI_LC chunks */
-
- static long twopos; /* To keep the file offset of frame # 2 */
-
- wwidth = header->fhd_width;
- wheight = header->fhd_height;
-
- for (i=0; i <= header->fhd_frames; i++)
- {
-
- /* The following stuff ist only needed if we display the frames
- while we interpret the file */
-
- /* If this is the first time through, we display frame # 1,
- otherwise, we skip right to frame two */
-
- if ((notfirst) && (i==0))
- {
- (void) lseek(fd, twopos, 0);
- continue;
- }
-
- /* If this is the first time through and we are at frame #2,
- save our file offset for the next loop through */
-
- if (!(notfirst) && (i==1))
- twopos = lseek(fd, 0, 1);
-
- /* Each frame has a header */
-
- read_fheader(fd, &fheader);
-
- for (j=0; j < fheader.fr_chunks; j++)
- {
- /* Each chunk also has a header */
- read_chunk(fd, &chunk);
-
- /* Malloc the space to hold whole chunk, unless it
- is a COPY chunk. Malloc/Realloc only if necessary */
-
- if (chunk.ch_type != FLI_COPY) {
- if (!buf)
- {
- buf = (unsigned char *)malloc(chunk.ch_bytes);
- bufalloc = chunk.ch_bytes;
- }
- else
- {
- if (bufalloc < chunk.ch_bytes)
- {
- buf = (unsigned char *)realloc(buf, chunk.ch_bytes);
- bufalloc = chunk.ch_bytes;
- }
- }
- }
-
- /* A COPY chunk means 64k of uncompressed image data,
- read it directly into the image */
-
- if (chunk.ch_type == FLI_COPY)
- s = read(fd, data, wwidth*wheight);
- else
- s = read(fd, buf, chunk.ch_bytes - 6);
-
- if (s < 0) {
- fprintf(stderr, "s: %d fd: %d data: 0x%x chunk.ch_bytes: %d\n",
- s, fd, data, chunk.ch_bytes);
- Crash("Error reading image data.");
- }
-
- cptr = buf;
-
- switch (chunk.ch_type) {
- case FLI_COPY:
- (*func)(FLI_COPY, i, data, 0,0, 0,0, wwidth,wheight);
- break;
-
- /* A BLACK chunk */
-
- case FLI_BLACK:
- bzero(data, wwidth * wheight);
- (*func)(FLI_BLACK, i, data, 0,0, 0,0, wwidth,wheight);
- break;
-
- /* A COLOR chunk: A compressed colormap to be stored or
- changed */
-
- case FLI_256_COLOR:
- npack = get_short(cptr);
- cptr += SHORTSIZE;
-
- for (l=0; l < npack; l++)
- {
- skcount = *(cptr++); /* # colors not to change */
- skchange = *(cptr++); /* # of colors to change */
- if (!skchange) /* (0 means all) */
- skchange=MAXCOL;
-
- /* The colors are stored in the right 6 bits
- of the byte. We then convert it to a short. */
-
- (*func)(FLI_256_COLOR, i, cptr, skcount,
- skchange, 0,0, 0,0);
- cptr += skchange * 3;
- }
- break;
-
- case FLI_COLOR:
- npack = get_short(cptr);
- cptr += SHORTSIZE;
-
- for (l=0; l < npack; l++)
- {
- skcount = *(cptr++); /* # colors not to change */
- skchange = *(cptr++); /* # of colors to change */
- if (!skchange) /* (0 means all) */
- skchange=MAXCOL;
-
- /* The colors are stored in the right 6 bits
- of the byte. We then convert it to a short. */
-
- (*func)(FLI_COLOR, i, cptr, skcount, skchange, 0,0, 0,0);
- cptr += skchange * 3;
- }
- break;
-
-
- /* Line compressed, and bytewise/run-length compressed
- chunks are similar. BRUN chunks always start at the
- top, while LC chunks can skip lines. Also, LC chunks
- can skip bytes on each line. The sign of the
- byte also has opposite meanings for the two! */
-
- case FLI_LC:
- curx = 0;
- cury = get_short(cptr); /* Lines at top to skip */
- cptr += SHORTSIZE;
- ndiff = get_short(cptr); /* # of lines different */
- cptr += SHORTSIZE;
-
- topy = cury;
- bottomy = cury + ndiff;
-
- leftx = wwidth;
- rightx = 0;
-
- for (k=0; k < ndiff; k++) /* Go through each line */
- {
- npack = *(cptr++); /* # packets this line */
-
- for (l=0; l < npack; l++)
- {
- skcount = *(cptr++); /* # bytes to skip */
-
- if (l == 0 && skcount < leftx)
- leftx = skcount;
-
- curx += skcount;
-
- /* The number of bytes in this packet to change */
-
- sicount = *(cptr++);
-
- /* Positive, for LC means bytes the changes follow,
- for BRUN means one byte to follow, spread it
- through. */
-
- if (sicount < 128)
- {
- bcopy(cptr, data + ((wwidth * cury) + curx),
- sicount);
- cptr += sicount;
- curx += sicount;
- }
-
- else
-
- /* Negative, the opposite */
-
- {
- sicount = 256 - sicount;
- by = *(cptr++);
- dptr = data + wwidth * cury + curx;
- eptr = dptr + sicount;
- do
- *(dptr++) = by;
- while (dptr < eptr);
- curx += sicount;
- }
- }
-
- if (curx > rightx)
- rightx = curx;
-
- /* Next line */
- cury++;
- curx = 0;
- }
-
- (*func)(FLI_LC, i, data, leftx,topy, leftx,topy,
- rightx-leftx,bottomy-topy);
- break;
-
- case FLI_DELTA:
- curx = 0;
- cury = 0;
-
- by0 = *(cptr++);
- by1 = *(cptr++);
- ndiff = by0 + 256 * by1; /* # of lines different */
-
- /* printf(" -- -- ndiff: %d frame: %d\n",ndiff,i); */
-
- topy = 0;
- bottomy = 0;
-
- leftx = wwidth;
- rightx = 0;
-
- k=0;
- while (k < ndiff) /* Go through each line */
- {
- by0 = *(cptr++);
- by1 = *(cptr++);
- npack = by0 + 256 * by1;
- if (npack >= 32768) npack -= 65536;
-
- /* printf(" -- npack: %d cury: %d\n",npack,cury); */
-
- if (npack < 0) /* skip lines */
- {
- if (cury == 0)
- {
- topy = -npack;
- }
- cury -= npack;
- continue;
- }
-
- bottomy = cury+1;
-
- for (l=0; l < npack; l++)
- {
- skcount = *(cptr++); /* # bytes to skip */
-
- if (l == 0 && skcount < leftx)
- leftx = skcount;
-
- curx += skcount;
- /* printf("pack: %d curx: %d skip: %d\n",
- l,curx,skcount); */
-
- /* The number of words in this packet to change */
-
- sicount = *(cptr++);
-
- /* Positive, for DELTA means sicount words (16 bit)
- that change follow */
- /* printf("sicount: %d\n",sicount); */
-
- if (sicount < 128)
- {
- bcopy(cptr, data + ((wwidth * cury) + curx),
- 2 * sicount);
- cptr += 2 * sicount;
- curx += 2 * sicount;
- }
-
- else
-
- /* Negative, the opposite */
-
- {
- sicount = 256 - sicount;
- by0 = *(cptr++);
- by1 = *(cptr++);
- dptr = data + wwidth * cury + curx;
- eptr = dptr + 2 * sicount;
- do
- {
- *(dptr++) = by0;
- *(dptr++) = by1;
- }
- while (dptr < eptr);
- curx += 2 * sicount;
- }
- }
-
- if (curx > rightx)
- rightx = curx;
-
- /* Next line */
- cury++;
- curx = 0;
- k++;
- }
-
- /* printf(" top: %d bot: %d left: %d right: %d\n",
- topy, bottomy, leftx, rightx); */
- (*func)(FLI_DELTA, i, data, leftx,topy, leftx,topy,
- rightx-leftx,bottomy-topy);
- break;
-
- case FLI_BRUN:
- dptr = data;
-
- for (k=0; k < wheight; k++) /* Go through each line */
- {
- npack = *(cptr++); /* # packets this line */
-
- for (l=0; l < npack; l++)
- {
- /* The number of bytes in this packet to change */
-
- sicount = *(cptr++);
-
- /* Positive, for LC means bytes the changes follow,
- for BRUN means one byte to follow, spread it
- through. */
-
- if (sicount < 128)
- {
- by = *cptr++;
- eptr = dptr + sicount;
- while (dptr < eptr)
- *(dptr++) = by;
- }
-
- /* Negative, the opposite */
-
- else
-
- {
- sicount = 256 - sicount;
- bcopy(cptr, dptr, sicount);
- cptr += sicount;
- dptr += sicount;
- }
- }
- }
-
- (*func)(FLI_BRUN, i, data, 0,0, 0,0, wwidth,wheight);
- break;
- }
-
- }
-
- /* Send a FLI_SYNC after each frame to get accurate timing */
- (*func)(FLI_SYNC, i, (unsigned char *)0, 0,0, 0,0, 0,0);
- }
-
- /* Only free the buffer if we allocated something */
- if (!buf)
- free(buf);
-
- }
-